
#include <BOpenGL>
#include <BRender>
#include <BSolverItem>
#include <BGridPlane>
#include "member_BGridPlane.h"

using namespace BWE;

#define member					(*(member_BGridPlane*)_ptr)
#define member_allocate()		_ptr = new member_BGridPlane(this)
#define member_release()		delete (member_BGridPlane*)_ptr

BGridPlane::BGridPlane()
{
	member_allocate();
}
BGridPlane::BGridPlane(const BVector& planeNormal, BReal constant)
{
	member_allocate();
	member.normal = planeNormal.normal();
	member.constant = constant;
}
BGridPlane::~BGridPlane()
{
	member_release();
}

void BGridPlane::copy(const BShape* other)
{

}
BShape* BGridPlane::clone() const
{
	return new BGridPlane(*this);
}

void BGridPlane::setNormal(const BVector& normal)
{
	if (member.normal != normal)
	{
		member.normal = normal;
		this->dirty();
	}
}
const BVector& BGridPlane::normal() const
{
	return member.normal;
}

void BGridPlane::setConstant(BReal constant)
{
	if (member.constant != constant)
	{
		member.constant = constant;
		this->dirty();
	}
}
BReal BGridPlane::constant() const
{
	return member.constant;
}

void BGridPlane::setCenter(const BVector& center)
{
	if (member.center != center)
	{
		member.center = center;
		this->dirty();
		this->emit(Signal_CenterChanged, center);
	}
}
const BVector& BGridPlane::center() const
{
	return member.center;
}

void BGridPlane::setGridSize(const BVector& gridSize)
{
	if (member.gridSize != gridSize)
	{
		member.gridSize = gridSize;
		this->dirty();
		this->emit(Signal_SizeChanged, gridSize);
	}
}
const BVector& BGridPlane::gridSize() const
{
	return member.gridSize;
}

void BGridPlane::setVerticalSegments(int verticalSegments)
{
	if (member.verticalSegments != verticalSegments)
	{
		member.verticalSegments = verticalSegments;
		this->dirty();
		this->emit(Signal_SegmentsChanged, verticalSegments);
	}
}
int BGridPlane::verticalSegments() const
{
	return member.verticalSegments;
}

void BGridPlane::setHorizontalSegments(int horizontalSegments)
{
	if (member.horizontalSegments != horizontalSegments)
	{
		member.horizontalSegments = horizontalSegments;
		this->dirty();
		this->emit(Signal_SegmentsChanged, horizontalSegments);
	}
}
int BGridPlane::horizontalSegments() const
{
	return member.horizontalSegments;
}

BVector BGridPlane::inertia(BReal mass) const
{
	return BVector();
}
BVector BGridPlane::vertex(const BVector& direct) const
{
	return BVector();
}

void BGridPlane::refresh(BBox& box)
{
	BVector horVec, verVec;
	PlaneSpace(member.normal, horVec, verVec);
	box.center() = member.center;
	box.dira() = horVec;
	box.dirb() = verVec;
	box.dirc() = member.normal;
	box.lena() = member.gridSize.x() / 2;
	box.lenb() = member.gridSize.y() / 2;
	box.lenc() = member.gridSize.z() / 2;

	horVec *= member.gridSize.x();
	verVec *= member.gridSize.y();

	member.horPoints.resize((member.horizontalSegments + 1) * 2);
	member.verPoints.resize((member.verticalSegments + 1) * 2);

	BVector origin = member.center - (horVec + verVec) / 2;

	BLine lineHor(origin, origin + horVec);
	BReal stepH = BReal(1) / member.horizontalSegments;
	for (int i = 0; i < member.horizontalSegments + 1; i++)
	{
		BVector v = lineHor.vertex(i * stepH);
		member.horPoints.set(i * 2, v);
		member.horPoints.set(i * 2 + 1, v + verVec);
	}

	BLine lineVer(origin, origin + verVec);
	BReal stepV = BReal(1) / member.verticalSegments;
	for (int i = 0; i < member.verticalSegments + 1; i++)
	{
		BVector v = lineVer.vertex(i * stepV);
		member.verPoints.set(i * 2, v);
		member.verPoints.set(i * 2 + 1, v + horVec);
	}

}
void BGridPlane::render(BRender& render)
{
	if (member.horPoints.size())
	{
		if (member.horColors.size())
		{
			glBegin(GL_LINES);
			int ic = 0;
			for (int i = 0; i < member.horPoints.size(); i += 2)
			{
				const BVector& p0 = member.horPoints[i];
				const BVector& p1 = member.horPoints[i + 1];
				const BColor& c = member.horColors.at(ic++);
				BOpenGL::glVertex(p0.x(), p0.y(), p0.z());
				BOpenGL::glVertex(p1.x(), p1.y(), p1.z());
				BOpenGL::glColor(c.r(), c.g(), c.b(), c.a());
			}
			glEnd();
		}
		else
		{
			render.drawLines(member.horPoints);
		}
	}
	if (member.verPoints.size())
	{
		if (member.verColors.size())
		{
			glBegin(GL_LINES);
			int ic = 0;
			for (int i = 0; i < member.verPoints.size(); i += 2)
			{
				const BVector& p0 = member.verPoints[i];
				const BVector& p1 = member.verPoints[i + 1];
				const BColor& c = member.verColors.at(ic++);
				BOpenGL::glVertex(p0.x(), p0.y(), p0.z());
				BOpenGL::glVertex(p1.x(), p1.y(), p1.z());
				BOpenGL::glColor(c.r(), c.g(), c.b(), c.a());
			}
			glEnd();
		}
		else
		{
			render.drawLines(member.verPoints);
		}
	}
}
